
void function($) {
	

	var template = {
		'img-getter': "<div class='img-getter-content'><input type='file' class='img-getter' /></div>",
		'img-viwer': "<div class='img-viwer-content'><img class='img-viwer' src='#' alt='图片加载失败' /></div>",
		'controller': "<div class='controller'><button class='rotate-left'>向左转</button><button class='rotate-right'>向右转</button><button class='scale-up'>放大</button><button class='scale-down'>缩小</button><button class='cancel'>取消</button><button class='done'>生成头像</button></div>",
		'box': "<div class='box'></div>",
		'move-listener': "<div class='move-listener'></div>",
		'blur': '<div class="blur"><div class="top"></div><div class="bottom"></div><div class="left"></div><div class="right"></div></div>'
	}
	var defaultOption = {
		size: 153,
		animation: {
			duration: 300,
			timingFunction: 'linear',
			delay: 0
		}
	}

	function picture_picker() {

	}

	picture_picker.prototype.init = function(dom, option) {
		var self = this;
		self.option = option || {};
		self.dom = dom;
		self.center = [$(dom).width() / 2, $(dom).height() / 2];
		self.imgSize = {
			width: 0,
			height: 0
		}
		$.extend(true, self, defaultOption, option);
		self.transformer = null;
		self.reset().render(dom).bindEvent(dom);
	}

	picture_picker.prototype.reset = function(opt) {
		var self = this;
		self.transformer = new transformer({
			top: 0,
			left: 0
		}, $(self.dom).offset(), {
			width: this.imgSize.width,
			height: this.imgSize.height
		})
		return self;
	}
	picture_picker.prototype.focusCenter = function() {
		var self = this, $dom = $(self.dom),
			view_size = self.transformer.viewSize(),
			r_s = self.transformer.absolutePoint([view_size.width / 2, view_size.height / 2]);
		self.transformer.move(self.center[0] - r_s[0], self.center[1] - r_s[1]);
		return self;
	}
	picture_picker.prototype.fitArea = function() {
		var self = this, $dom = $(self.dom),
			view_size = self.transformer.viewSize();
		self.scale($dom.width() / view_size.width);
		return self;
	}

	picture_picker.prototype.render = function(dom) {
		var self = this, $dom = $(dom);
		for (var i in template) {
			if (!$dom.find('.' + i).length) {
				$dom.append($(template[i]));
			}
		}
		$dom.find('.box').width(self.size).height(self.size);

		var domSize = [$dom.width(), $dom.height()],
		    topSize = [domSize[0], (domSize[1] - self.size) / 2],
			bottomSize = [domSize[0], (domSize[1] - self.size) / 2],
			leftSize = [(domSize[0] - self.size) / 2, self.size],
			rightSize = [(domSize[0] - self.size) / 2, self.size];

		$dom
		.find('.blur .top').width(topSize[0]).height(topSize[1])
		.end().find('.blur .bottom').width(bottomSize[0]).height(bottomSize[1])
		.end().find('.blur .left').width(leftSize[0]).height(leftSize[1]).css('top', topSize[1])
		.end().find('.blur .right').width(rightSize[0]).height(rightSize[1]).css('top', topSize[1]);

		return self;
	}

	picture_picker.prototype.imgChange = function(url) {
		var self = this;

		$(self.dom)
		.find('.img-viwer')
		.attr('src', url)
		.one('load', function(e) {
			
			self.imgSize.width = this.naturalWidth;
			self.imgSize.height = this.naturalHeight;
			self
			.reset()
			.initImagePosition()
			.updateImagePosition()
			.show()
		})
		.one('error', function(e) {
			self.hide();
		})
		return self;
	}

	picture_picker.prototype.moveImg = function(dis) {
		var self = this;
		self.transformer.move(dis.x, dis.y);
		return self;
	}

	picture_picker.prototype.initImagePosition = function() {
		var self = this;
		self
			.fitArea()
			.focusCenter();
		return self;
	}

	picture_picker.prototype.updateImagePosition = function() {
		var self = this, $dom = $(self.dom);
		$dom
			.find('.img-viwer-content').css(self.transformer.getStyle());
		return self;
	}

	picture_picker.prototype.rotate = function(v) {
		var self = this;
		self.transformer.rotate(self.center, v);
		return self;
	}

	picture_picker.prototype.rotateLeft = function() {
		var self = this;
		self.rotate(-30);
		return self;
	}

	picture_picker.prototype.rotateRight = function() {
		var self = this;
		self.rotate(30);
		return self;
	}

	picture_picker.prototype.scale = function(v) {
		var self = this;
		self.transformer.scale(self.center, v);
		return self;
	}

	picture_picker.prototype.scaleUp = function() {
		var self = this;
		self.scale(1.2);
		return self;
	}

	picture_picker.prototype.scaleDown = function() {
		var self = this;
		self.scale(1/1.2);
		return self;
	}

	picture_picker.prototype.show = function() {
		var self = this;
		$(self.dom).addClass('active');
		return self;
	}

	picture_picker.prototype.hide = function() {
		var self = this;
		$(self.dom).removeClass('active');
		return self;
	}

	picture_picker.prototype.getPicture = function() {
		var self = this;
		var $dom = $(self.dom),
			transform = self.transformer.transform;
		
		var original_canvas = document.createElement('canvas');
		original_canvas.width = self.imgSize.width;
		original_canvas.height = self.imgSize.height;
		original_canvas.getContext('2d').drawImage($dom.find('.img-viwer')[0], 0, 0, self.imgSize.width, self.imgSize.height, 0, 0, self.imgSize.width, self.imgSize.height);
		
		var temp = document.createElement('canvas'),
			target = document.createElement('canvas'),
			size = self.size / transform.scale,
			xb = Math.sqrt(2) * size,
			rc = self.transformer.relativePoint(self.center).map(function(t) { return t / transform.scale; });

		temp.width = temp.height = xb;
		target.width = target.height = size;

		temp.getContext('2d').drawImage(original_canvas, rc[0] - xb / 2, rc[1] - xb / 2, xb, xb, 0, 0, xb, xb);
		rotate(temp, self.transformer.transform.degree);
		target.getContext('2d').drawImage(temp, (xb - size) / 2, (xb - size) / 2, size, size, 0, 0, size, size);
	
		// return [temp, target];
		return scale({
			width: self.size,
			height: self.size
		}, target, 'jpeg');

	}

	picture_picker.prototype.bindEvent = function(dom) {
		var self = this, $dom = $(dom);
		if ($dom.data('binded')) {
			return;
		}
		var x, y, moving = false;
		var animating = false;

		var animate = function() {
			animating = true;
			self.transformer
				.animator($dom.find('.img-viwer-content'), $dom, self.animation)
					.done(function() {
						animating = false;
					})
					.start();
		}

		$dom
		.data('binded', true)
		.on('selectstart', function(e) {
			console.log('please remove this output');
			e.preventDefault();
			return false;
		})
		.find('.move-listener').on({
			'mousedown': function(e) {
				x = e.clientX;
				y = e.clientY;
				moving = true;
			},
			'mousemove': function(e) {
				if (!moving || !$dom.is('.active')) {
					return;
				}
				self.moveImg({
					x: e.clientX - x,
					y: e.clientY - y
				}).updateImagePosition();
				x = e.clientX;
				y = e.clientY;
			},
			'mouseup mouseleave': function(e) {
				moving = false;
			}
		})
		.end()
		.find('.img-getter').on('change', function(e) {
			if (this.files[0] && /image\/\w+/.test(this.files[0].type)) {
				self.imgChange(getObjectURL(this.files[0]));
				this.value = '';
			} else {
				// not image get
				this.value = '';
			}
		})
		.end()
		.on('click', '.controller .rotate-left', function() {
			if (animating) {
				return;
			}
			self.rotateLeft().updateImagePosition();
			animate();
		})
		.on('click', '.controller .rotate-right', function() {
			if (animating) {
				return;
			}
			self.rotateRight().updateImagePosition();
			animate();
		})
		.on('click', '.controller .scale-up', function() {
			if (animating) {
				return;
			}
			self.scaleUp().updateImagePosition();
			animate();
		})
		.on('click', '.controller .scale-down', function() {
			if (animating) {
				return;
			}
			self.scaleDown().updateImagePosition();
			animate();
		})
		.on('click', '.controller .done', function() {
			$dom.trigger('imageCreate', [self.getPicture()]);
		})
		.on('click', '.controller .cancel', function() {
			self.hide();
		})
		return self;
	}

// util

function getObjectURL(file){   
    var url=null    
    if(window.createObjectURL!=undefined){ // basic
        url=window.createObjectURL(file)   
    }else if(window.URL!=undefined){ // mozilla(firefox)
        url=window.URL.createObjectURL(file)   
    } else if(window.webkitURL!=undefined){ // webkit or chrome
        url=window.webkitURL.createObjectURL(file)   
    }   
    return url   
}  


function rotate(canva, degrees) {
  var angle = degrees * Math.PI / 180;
  var ctx = canva.getContext("2d"), img = document.createElement('canvas');
  // var dataImg = ctx.getImageData(0, 0, canva.width, canva.height);
  var center = {
    x: canva.width / 2,
    y: canva.height / 2
  };

  copy(canva, img);

  ctx.clearRect(0, 0, canva.width, canva.height);
  ctx.translate(center.x, center.y);
  ctx.rotate(angle);
  // ctx.fillRect(0, 0, canva.width, canva.height);
  ctx.drawImage(img, 0, 0, canva.width, canva.height, -center.x, -center.y, canva.width, canva.height);
  
  ctx.rotate(-angle);
  ctx.translate(-center.x, -center.y);

  return canva;
}

function copy(canva, target) {
    var ctx = target.getContext("2d"),
    fromCtx = canva.getContext('2d');
    var dataImg = fromCtx.getImageData(0, 0, canva.width, canva.height);
    
    target.width = canva.width;
    target.height = canva.height;

    ctx.putImageData(dataImg, 0, 0);
    return target;
}



picture_picker.init = function(dom, option) {
	var obj = new picture_picker();
	obj.init(dom, option);
}

window.picture_picker = picture_picker;

$.fn.picture_picker = function(option) {
	return this.each(function() {
		picture_picker.init(this, option);
	});
}

}(jQuery);